
namespace SharpTalk.Core
{
    using System;
    using System.Collections.ObjectModel;
    using Base;
    using EventArgs;
    using Services;

    /// <summary>
    /// 
    /// </summary>
    public sealed class Discussion : PropertyChangedBase, IEquatable<Discussion>
    {
        /// <summary>
        /// Occurs when a message is truncated
        /// </summary>
        public event EventHandler<SimpleMessageTruncatedEventArgs> SimpleMessageTruncated;
        
        private ChatRoomDetails _chatroom;
        private ObservableCollection<User> _users;
        private string _currentText;
        private readonly SimpleMessageCollection _messages;

        private Discussion(){}
       
        /// <summary>
        /// Creates a new Discussion
        /// </summary>
        /// <param name="chatroom">The chatroom attached</param>
        /// <param name="maxMessagesCount">The maximum messages count</param>
        public Discussion(ChatRoomDetails chatroom, int maxMessagesCount)
        {
            if (chatroom == null) throw new ArgumentNullException("chatroom");
            _chatroom = chatroom;
            _users = new ObservableCollection<User>();
            _messages = new SimpleMessageCollection(maxMessagesCount);
            _messages.ItemTruncated += (s, e) => InvokeSimpleMessageTruncated( new SimpleMessageTruncatedEventArgs(e.Item,chatroom) );

            if (!string.IsNullOrEmpty(_chatroom.Motd))
                _messages.AddItem(new SimpleMessage() { IsNotMotd = false, Content = _chatroom.Motd, Owner = UserService.GetSystemUser().Guid });
        }

        /// <summary>
        /// Adds a SimpleMessage to the discussion
        /// </summary>
        /// <param name="message"></param>
        public void AddMessage(SimpleMessage message)
        {
            if(message!=null)
                _messages.AddItem(message);
        }

        /// <summary>
        /// Obtains or defines the ChatroomDetails
        /// </summary>
        public ChatRoomDetails Chatroom
        {
            get { return _chatroom; }
            set { _chatroom = value;  NotifyPropertyChange(()=>Chatroom);}
        }
        /// <summary>
        /// Obtains or defines the users
        /// </summary>
        public ObservableCollection<User> Users
        {
            get { return _users; }
            set { _users = value; NotifyPropertyChange(()=>Users); }
        }
        /// <summary>
        /// Obtains the messages collection
        /// </summary>
        public SimpleMessageCollection Messages
        {
            get { return _messages; }
        }
        /// <summary>
        /// Current typed text
        /// </summary>
        public string CurrentText
        {
            get { return _currentText; }
            set
            {
                _currentText = value; 
                if(!string.IsNullOrEmpty(_currentText) && _currentText.IndexOf(Environment.NewLine) > -1)
                    NotifyPropertyChange(() => CurrentText);
            }
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <returns>
        /// true if the current object is equal to the <paramref name="other"/> parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(Discussion other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other._chatroom, _chatroom);
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param><filterpriority>2</filterpriority>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (Discussion)) return false;
            return Equals((Discussion) obj);
        }

        /// <summary>
        /// Serves as a hash function for a particular type. 
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        /// <filterpriority>2</filterpriority>
        public override int GetHashCode()
        {
            return (_chatroom != null ? _chatroom.GetHashCode() : 0);
        }

        public static bool operator ==(Discussion left, Discussion right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(Discussion left, Discussion right)
        {
            return !Equals(left, right);
        }

        private void InvokeSimpleMessageTruncated(SimpleMessageTruncatedEventArgs e)
        {
            var handler = SimpleMessageTruncated;
            if (handler != null) handler(this, e);
        }

    }
}